xk6-frostfs/internal/datagen/generator.go

81 lines
1.8 KiB
Go

package datagen
import (
"crypto/sha256"
"encoding/hex"
"math/rand"
"time"
"github.com/dop251/goja"
"go.k6.io/k6/js/modules"
)
type (
// Generator stores buffer of random bytes with some tail and returns data slices with
// an increasing offset so that we receive a different set of bytes after each call without
// re-generation of the entire buffer from scratch:
//
// [<----------size----------><-tail->]
// [<----------slice0-------->........]
// [.<----------slice1-------->.......]
// [..<----------slice2-------->......]
Generator struct {
vu modules.VU
size int
buf []byte
offset int
}
GenPayloadResponse struct {
Payload goja.ArrayBuffer
Hash string
}
)
// TailSize specifies number of extra random bytes in the buffer tail.
const TailSize = 1024
func init() {
rand.Seed(time.Now().UnixNano())
}
func NewGenerator(vu modules.VU, size int) Generator {
if size <= 0 {
panic("size should be positive")
}
return Generator{vu: vu, size: size, buf: nil, offset: 0}
}
func (g *Generator) GenPayload(calcHash bool) GenPayloadResponse {
data := g.nextSlice()
dataHash := ""
if calcHash {
hashBytes := sha256.Sum256(data)
dataHash = hex.EncodeToString(hashBytes[:])
}
payload := g.vu.Runtime().NewArrayBuffer(data)
return GenPayloadResponse{Payload: payload, Hash: dataHash}
}
func (g *Generator) nextSlice() []byte {
if g.buf == nil {
// Allocate buffer with extra tail for sliding and populate it with random bytes
g.buf = make([]byte, g.size+TailSize)
rand.Read(g.buf) // Per docs, err is always nil here
}
result := g.buf[g.offset : g.offset+g.size]
// Shift the offset for the next call. If we've used our entire tail, then erase
// the buffer so that on the next call it is regenerated anew
g.offset += 1
if g.offset >= TailSize {
g.buf = nil
g.offset = 0
}
return result
}