You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
7.5 KiB
Go
253 lines
7.5 KiB
Go
package chunking
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"errors"
|
|
"io"
|
|
"testing"
|
|
)
|
|
|
|
// Test_ChunkerEmptyReader tests that a Chunker created with an empty reader
|
|
// returns io.EOF on the first call to Next.
|
|
func Test_ChunkerEmptyReader(t *testing.T) {
|
|
// Create an empty reader that immediately returns io.EOF
|
|
r := bytes.NewReader([]byte{})
|
|
chunker := NewChunker(r, 1024)
|
|
|
|
// Expect the first call to Next to return io.EOF
|
|
_, err := chunker.Next()
|
|
if err != io.EOF {
|
|
t.Fatalf("expected io.EOF, got %v", err)
|
|
}
|
|
|
|
// Further calls to Next should also return io.EOF
|
|
_, err = chunker.Next()
|
|
if err != io.EOF {
|
|
t.Fatalf("expected io.EOF, got %v", err)
|
|
}
|
|
}
|
|
|
|
// Test_ChunkerSingleChunk tests that a Chunker created with a reader that
|
|
// contains a single chunk returns the expected chunk, when the chunk size is
|
|
// larger than the amount of data in the reader.
|
|
func Test_ChunkerSingleChunk(t *testing.T) {
|
|
data := []byte("Hello, world!")
|
|
chunker := NewChunker(bytes.NewReader(data), 32)
|
|
|
|
chunk, err := chunker.Next()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if chunk.SequenceNum != 1 {
|
|
t.Errorf("unexpected sequence number: got %d, want %d", chunk.SequenceNum, 1)
|
|
}
|
|
if !chunk.IsLast {
|
|
t.Errorf("unexpected IsLast value: got %v, want %v", chunk.IsLast, true)
|
|
}
|
|
|
|
// Decompress the gzip data and compare it with expected
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(chunk.Data))
|
|
if err != nil {
|
|
t.Fatalf("failed to create gzip reader: %v", err)
|
|
}
|
|
defer gzipReader.Close()
|
|
|
|
decompressed := new(bytes.Buffer)
|
|
if _, err = io.Copy(decompressed, gzipReader); err != nil {
|
|
t.Fatalf("failed to decompress data: %v", err)
|
|
}
|
|
|
|
if decompressed.String() != string(data) {
|
|
t.Errorf("unexpected chunk data: got %s, want %s", decompressed.String(), string(data))
|
|
}
|
|
|
|
// After all chunks are read, Next should return nil, io.EOF
|
|
chunk, err = chunker.Next()
|
|
if chunk != nil || err != io.EOF {
|
|
t.Errorf("expected (nil, io.EOF), got (%v, %v)", chunk, err)
|
|
}
|
|
}
|
|
|
|
func Test_ChunkerAbort(t *testing.T) {
|
|
data := []byte("Hello, world!")
|
|
chunker := NewChunker(bytes.NewReader(data), 32)
|
|
chunk := chunker.Abort()
|
|
if chunk.Abort != true {
|
|
t.Errorf("expected Abort to be true, got %v", chunk.Abort)
|
|
}
|
|
}
|
|
|
|
// Test_ChunkerSingleChunkLarge tests that a Chunker created with a reader that
|
|
// contains a single chunk returns the expected chunk, when the chunk size is
|
|
// much larger than the amount of data in the reader, and is larger than the
|
|
// internal chunk size.
|
|
func Test_ChunkerSingleChunkLarge(t *testing.T) {
|
|
data := []byte("Hello, world!")
|
|
chunker := NewChunker(bytes.NewReader(data), internalChunkSize*3)
|
|
|
|
chunk, err := chunker.Next()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if chunk.SequenceNum != 1 {
|
|
t.Errorf("unexpected sequence number: got %d, want %d", chunk.SequenceNum, 1)
|
|
}
|
|
if !chunk.IsLast {
|
|
t.Errorf("unexpected IsLast value: got %v, want %v", chunk.IsLast, true)
|
|
}
|
|
|
|
// Decompress the gzip data and compare it with expected
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(chunk.Data))
|
|
if err != nil {
|
|
t.Fatalf("failed to create gzip reader: %v", err)
|
|
}
|
|
defer gzipReader.Close()
|
|
|
|
decompressed := new(bytes.Buffer)
|
|
if _, err = io.Copy(decompressed, gzipReader); err != nil {
|
|
t.Fatalf("failed to decompress data: %v", err)
|
|
}
|
|
|
|
if decompressed.String() != string(data) {
|
|
t.Errorf("unexpected chunk data: got %s, want %s", decompressed.String(), string(data))
|
|
}
|
|
|
|
// After all chunks are read, Next should return nil, io.EOF
|
|
chunk, err = chunker.Next()
|
|
if chunk != nil || err != io.EOF {
|
|
t.Errorf("expected (nil, io.EOF), got (%v, %v)", chunk, err)
|
|
}
|
|
}
|
|
|
|
// Test_ChunkerSingleChunkExact tests that a Chunker created with a reader that
|
|
// contains a single chunk returns the expected chunk, when the chunk size is
|
|
// exactly the size of amount of data in the reader.
|
|
func Test_ChunkerSingleChunkExact(t *testing.T) {
|
|
data := []byte("Hello")
|
|
chunker := NewChunker(bytes.NewReader(data), 5)
|
|
|
|
chunk, err := chunker.Next()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// The expected sequence number should be 1
|
|
if chunk.SequenceNum != 1 {
|
|
t.Errorf("unexpected sequence number: got %d, want %d", chunk.SequenceNum, 1)
|
|
}
|
|
|
|
// Won't be last since chunker doesn't know the size of the data
|
|
if chunk.IsLast {
|
|
t.Errorf("unexpected IsLast value: got %v, want %v", chunk.IsLast, true)
|
|
}
|
|
|
|
// Decompress the gzip data and compare it with expected
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(chunk.Data))
|
|
if err != nil {
|
|
t.Fatalf("failed to create gzip reader: %v", err)
|
|
}
|
|
defer gzipReader.Close()
|
|
|
|
decompressed := new(bytes.Buffer)
|
|
if _, err = io.Copy(decompressed, gzipReader); err != nil {
|
|
t.Fatalf("failed to decompress data: %v", err)
|
|
}
|
|
|
|
if decompressed.String() != string(data) {
|
|
t.Errorf("unexpected chunk data: got %s, want %s", decompressed.String(), string(data))
|
|
}
|
|
|
|
// Call Next again, get a second chunk, which should be the last chunk
|
|
chunk, err = chunker.Next()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if chunk.SequenceNum != 2 {
|
|
t.Errorf("unexpected sequence number: got %d, want %d", chunk.SequenceNum, 2)
|
|
}
|
|
if !chunk.IsLast {
|
|
t.Errorf("unexpected IsLast value: got %v, want %v", chunk.IsLast, true)
|
|
}
|
|
if chunk.Data != nil {
|
|
t.Errorf("unexpected chunk data: got %v, want %v", chunk.Data, nil)
|
|
}
|
|
|
|
// After all chunks are read, Next should return nil, io.EOF
|
|
chunk, err = chunker.Next()
|
|
if chunk != nil || err != io.EOF {
|
|
t.Errorf("expected (nil, io.EOF), got (%v, %v)", chunk, err)
|
|
}
|
|
}
|
|
|
|
// Test_ChunkerMultiChunks tests that a Chunker created with a reader which contains
|
|
// enough data that multiple chunks should be returned, returns the expected chunks.
|
|
func Test_ChunkerMultiChunks(t *testing.T) {
|
|
data := []byte("Hello, world!")
|
|
chunkSize := int64(5)
|
|
|
|
chunker := NewChunker(bytes.NewReader(data), chunkSize)
|
|
|
|
expectedChunks := []string{
|
|
"Hello",
|
|
", wor",
|
|
"ld!",
|
|
}
|
|
|
|
for i, expected := range expectedChunks {
|
|
chunk, err := chunker.Next()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// The expected sequence number should be i+1
|
|
if chunk.SequenceNum != int64(i+1) {
|
|
t.Errorf("unexpected sequence number: got %d, want %d", chunk.SequenceNum, i+1)
|
|
}
|
|
|
|
// The expected IsLast value should be true only for the last chunk
|
|
expectedIsLast := i == len(expectedChunks)-1
|
|
if chunk.IsLast != expectedIsLast {
|
|
t.Errorf("unexpected IsLast value: got %v, want %v", chunk.IsLast, expectedIsLast)
|
|
}
|
|
|
|
// Decompress the gzip data and compare it with expected
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(chunk.Data))
|
|
if err != nil {
|
|
t.Fatalf("failed to create gzip reader: %v", err)
|
|
}
|
|
defer gzipReader.Close()
|
|
|
|
decompressed := new(bytes.Buffer)
|
|
if _, err = io.Copy(decompressed, gzipReader); err != nil {
|
|
t.Fatalf("failed to decompress data: %v", err)
|
|
}
|
|
|
|
if decompressed.String() != expected {
|
|
t.Errorf("unexpected chunk data: got %s, want %s", decompressed.String(), expected)
|
|
}
|
|
}
|
|
|
|
// After all chunks are read, Next should return nil, io.EOF
|
|
chunk, err := chunker.Next()
|
|
if chunk != nil || err != io.EOF {
|
|
t.Errorf("expected (nil, io.EOF), got (%v, %v)", chunk, err)
|
|
}
|
|
}
|
|
|
|
type errorReader struct{}
|
|
|
|
func (r *errorReader) Read([]byte) (int, error) {
|
|
return 0, errors.New("test error")
|
|
}
|
|
|
|
// Test_ChunkerReaderError tests that a Chunker created with a reader that
|
|
// returns an error other than io.EOF returns that error.
|
|
func Test_ChunkerReaderError(t *testing.T) {
|
|
chunker := NewChunker(&errorReader{}, 1024)
|
|
_, err := chunker.Next()
|
|
if err == nil || err.Error() != "test error" {
|
|
t.Errorf("expected test error, got %v", err)
|
|
}
|
|
}
|