github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/memsys/iosgl_test.go (about)

     1  // Package memsys provides memory management and Slab allocation
     2  // with io.Reader and io.Writer interfaces on top of a scatter-gather lists
     3  // (of reusable buffers)
     4  /*
     5   * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
     6   */
     7  package memsys_test
     8  
     9  import (
    10  	"bytes"
    11  	"io"
    12  	"strings"
    13  	"testing/iotest"
    14  
    15  	"github.com/NVIDIA/aistore/cmn/cos"
    16  	"github.com/NVIDIA/aistore/memsys"
    17  	"github.com/NVIDIA/aistore/tools/cryptorand"
    18  	. "github.com/onsi/ginkgo/v2"
    19  	. "github.com/onsi/gomega"
    20  )
    21  
    22  func randReader(size int64) ([]byte, io.Reader) {
    23  	buf := make([]byte, size)
    24  	cryptorand.Read(buf)
    25  	return buf, bytes.NewBuffer(buf)
    26  }
    27  
    28  var _ = Describe("SGL", func() {
    29  	mm := memsys.PageMM()
    30  
    31  	It("should perform write and read for SGL", func() {
    32  		sgl := mm.NewSGL(0)
    33  		err := cos.FloodWriter(sgl, 10*cos.MiB)
    34  		Expect(err).ToNot(HaveOccurred())
    35  		err = iotest.TestReader(sgl, sgl.Bytes())
    36  		Expect(err).ToNot(HaveOccurred())
    37  	})
    38  
    39  	It("should read lines from SGL", func() {
    40  		rnd := cos.NowRand()
    41  		sgl := mm.NewSGL(0)
    42  		num := int(rnd.Int63n(1000) + 1)
    43  		arr := make([]string, num)
    44  		str := []byte("A")
    45  		for i := range num {
    46  			str[0] = byte('A' + i%26)
    47  			// NOTE in re (+1): skipping zero-length lines
    48  			arr[i] = strings.Repeat(string(str), int(rnd.Int63n(256)+1)) + "\n"
    49  			sgl.Write([]byte(arr[i]))
    50  		}
    51  		i := 0
    52  		for {
    53  			line, err := sgl.NextLine(nil, true)
    54  			if err == io.EOF {
    55  				break
    56  			}
    57  			Expect(err).ToNot(HaveOccurred())
    58  			l := len(arr[i])
    59  			Expect(line).To(BeEquivalentTo([]byte(arr[i][:l-1])))
    60  			i++
    61  		}
    62  		Expect(i).To(Equal(num))
    63  	})
    64  
    65  	It("should properly write to SGL using WriteByte method", func() {
    66  		size := int64(cos.MiB)
    67  		buf, _ := randReader(size)
    68  
    69  		sgl := mm.NewSGL(cos.KiB)
    70  
    71  		for i := range size {
    72  			err := sgl.WriteByte(buf[i])
    73  			Expect(err).ToNot(HaveOccurred())
    74  		}
    75  		b := sgl.ReadAll()
    76  		Expect(b).To(HaveLen(int(size)))
    77  		Expect(b).To(BeEquivalentTo(buf))
    78  	})
    79  
    80  	Describe("ReadFrom", func() {
    81  		It("should properly write to SGL using ReadFrom method", func() {
    82  			size := int64(11*cos.MiB + 2*cos.KiB + 123)
    83  			buf, r := randReader(size)
    84  
    85  			sgl := mm.NewSGL(0)
    86  
    87  			n, err := sgl.ReadFrom(r)
    88  			Expect(err).ToNot(HaveOccurred())
    89  			Expect(n).To(Equal(size))
    90  
    91  			b := sgl.ReadAll()
    92  			Expect(b).To(HaveLen(int(size)))
    93  			Expect(b).To(BeEquivalentTo(buf))
    94  		})
    95  
    96  		It("should properly write to SGL with big slab using ReadFrom method", func() {
    97  			size := int64(11*cos.MiB + 2*cos.KiB + 123)
    98  			buf, r := randReader(size)
    99  
   100  			sgl := mm.NewSGL(0, memsys.MaxPageSlabSize)
   101  
   102  			n, err := sgl.ReadFrom(r)
   103  			Expect(err).ToNot(HaveOccurred())
   104  			Expect(n).To(Equal(size))
   105  
   106  			b := sgl.ReadAll()
   107  			Expect(b).To(HaveLen(int(size)))
   108  			Expect(b).To(BeEquivalentTo(buf))
   109  		})
   110  
   111  		It("should properly write to preallocated SGL using ReadFrom method", func() {
   112  			size := int64(11*cos.MiB + 2*cos.KiB + 123)
   113  			buf, r := randReader(size)
   114  
   115  			sgl := mm.NewSGL(size)
   116  
   117  			n, err := sgl.ReadFrom(r)
   118  			Expect(err).ToNot(HaveOccurred())
   119  			Expect(n).To(Equal(size))
   120  
   121  			b := sgl.ReadAll()
   122  			Expect(b).To(HaveLen(int(size)))
   123  			Expect(b).To(BeEquivalentTo(buf))
   124  		})
   125  
   126  		It("should properly write multiple times to SGL using ReadFrom method", func() {
   127  			size := int64(11*cos.MiB + 2*cos.KiB + 123)
   128  			_, r := randReader(size)
   129  
   130  			sgl := mm.NewSGL(size)
   131  			n, err := sgl.ReadFrom(r)
   132  			Expect(err).ToNot(HaveOccurred())
   133  			Expect(n).To(Equal(size))
   134  
   135  			_, r = randReader(size)
   136  			n, err = sgl.ReadFrom(r)
   137  			Expect(err).ToNot(HaveOccurred())
   138  			Expect(n).To(Equal(size))
   139  
   140  			b := sgl.ReadAll()
   141  			Expect(b).To(HaveLen(2 * int(size)))
   142  		})
   143  	})
   144  })