183 lines · 4.8 KB · Go
RawDownload
// Copyright (c) 2015-2021 MinIO, Inc.//// This file is part of MinIO Object Storage stack//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program.  If not, see <http://www.gnu.org/licenses/>. package cmd import (	"bytes"	"errors"	"fmt"	"io"	"io/ioutil"	"testing") var alphabets = []byte("abcdefghijklmnopqrstuvwxyz0123456789") // DummyDataGen returns a reader that repeats the bytes in `alphabets`// upto the desired length.type DummyDataGen struct {	b           []byte	idx, length int64} // NewDummyDataGen returns a ReadSeeker over the first `totalLength`// bytes from the infinite stream consisting of repeated// concatenations of `alphabets`.//// The skipOffset (generally = 0) can be used to skip a given number// of bytes from the beginning of the infinite stream. This is useful// to compare such streams of bytes that may be split up, because://// Given the function://// f := func(r io.Reader) string {//           b, _ := ioutil.ReadAll(r)//           return string(b)// }//// for example, the following is true://// f(NewDummyDataGen(100, 0)) == f(NewDummyDataGen(50, 0)) + f(NewDummyDataGen(50, 50))func NewDummyDataGen(totalLength, skipOffset int64) io.ReadSeeker {	if totalLength < 0 {		panic("Negative length passed to DummyDataGen!")	}	if skipOffset < 0 {		panic("Negative rotations are not allowed")	} 	skipOffset %= int64(len(alphabets))	as := make([]byte, 2*len(alphabets))	copy(as, alphabets)	copy(as[len(alphabets):], alphabets)	b := as[skipOffset : skipOffset+int64(len(alphabets))]	return &DummyDataGen{		length: totalLength,		b:      b,	}} func (d *DummyDataGen) Read(b []byte) (n int, err error) {	k := len(b)	numLetters := int64(len(d.b))	for k > 0 && d.idx < d.length {		w := copy(b[len(b)-k:], d.b[d.idx%numLetters:])		k -= w		d.idx += int64(w)		n += w	}	if d.idx >= d.length {		extraBytes := d.idx - d.length		n -= int(extraBytes)		if n < 0 {			n = 0		}		err = io.EOF	}	return} func (d *DummyDataGen) Seek(offset int64, whence int) (int64, error) {	switch whence {	case io.SeekStart:		if offset < 0 {			return 0, errors.New("Invalid offset")		}		d.idx = offset	case io.SeekCurrent:		if d.idx+offset < 0 {			return 0, errors.New("Invalid offset")		}		d.idx += offset	case io.SeekEnd:		if d.length+offset < 0 {			return 0, errors.New("Invalid offset")		}		d.idx = d.length + offset	}	return d.idx, nil} func TestDummyDataGenerator(t *testing.T) {	readAll := func(r io.Reader) string {		b, _ := ioutil.ReadAll(r)		return string(b)	}	checkEq := func(a, b string) {		if a != b {			t.Fatalf("Unexpected equality failure")		}	} 	checkEq(readAll(NewDummyDataGen(0, 0)), "") 	checkEq(readAll(NewDummyDataGen(10, 0)), readAll(NewDummyDataGen(10, int64(len(alphabets))))) 	checkEq(readAll(NewDummyDataGen(100, 0)), readAll(NewDummyDataGen(50, 0))+readAll(NewDummyDataGen(50, 50))) 	r := NewDummyDataGen(100, 0)	r.Seek(int64(len(alphabets)), 0)	checkEq(readAll(r), readAll(NewDummyDataGen(100-int64(len(alphabets)), 0)))} // Compares all the bytes returned by the given readers. Any Read// errors cause a `false` result. A string describing the error is// also returned.func cmpReaders(r1, r2 io.Reader) (bool, string) {	bufLen := 32 * 1024	b1, b2 := make([]byte, bufLen), make([]byte, bufLen)	for i := 0; true; i++ {		n1, e1 := io.ReadFull(r1, b1)		n2, e2 := io.ReadFull(r2, b2)		if n1 != n2 {			return false, fmt.Sprintf("Read %d != %d bytes from the readers", n1, n2)		}		if !bytes.Equal(b1[:n1], b2[:n2]) {			return false, fmt.Sprintf("After reading %d equal buffers (32Kib each), we got the following two strings:\n%v\n%v\n",				i, b1, b2)		}		// Check if stream has ended		if (e1 == io.ErrUnexpectedEOF && e2 == io.ErrUnexpectedEOF) || (e1 == io.EOF && e2 == io.EOF) {			break		}		if e1 != nil || e2 != nil {			return false, fmt.Sprintf("Got unexpected error values: %v == %v", e1, e2)		}	}	return true, ""} func TestCmpReaders(t *testing.T) {	{		r1 := bytes.NewReader([]byte("abc"))		r2 := bytes.NewReader([]byte("abc"))		ok, msg := cmpReaders(r1, r2)		if !(ok && msg == "") {			t.Fatalf("unexpected")		}	} 	{		r1 := bytes.NewReader([]byte("abc"))		r2 := bytes.NewReader([]byte("abcd"))		ok, _ := cmpReaders(r1, r2)		if ok {			t.Fatalf("unexpected")		}	}}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t