blob: d45ae9980bbacf01c1dcb35f525c0feff4cf787b [file] [log] [blame]
// Copyright 2019 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package testcut provides support for testing flatecut and zlibcut.
package testcut
import (
"bytes"
"io"
"io/ioutil"
"testing"
)
func calculateDecodedLen(b []byte,
newReader func(io.Reader) (io.ReadCloser, error)) (int64, error) {
r, err := newReader(bytes.NewReader(b))
if err != nil {
return 0, err
}
n, err := io.Copy(ioutil.Discard, r)
if err != nil {
r.Close()
return 0, err
}
return n, r.Close()
}
func clone(b []byte) []byte {
return append([]byte(nil), b...)
}
func Test(tt *testing.T,
smallestValidMaxEncodedLen int,
cut func(io.Writer, []byte, int) (int, int, error),
newReader func(io.Reader) (io.ReadCloser, error),
filenames []string) {
for _, filename := range filenames {
full, err := ioutil.ReadFile("../../test/data/" + filename)
if err != nil {
tt.Errorf("f=%q: ReadFile: %v", filename, err)
continue
}
fullDecodedLen, err := calculateDecodedLen(full, newReader)
if err != nil {
tt.Errorf("f=%q: calculateDecodedLen: %v", filename, err)
continue
}
maxEncodedLens := []int{
smallestValidMaxEncodedLen + 0,
smallestValidMaxEncodedLen + 1,
smallestValidMaxEncodedLen + 2,
smallestValidMaxEncodedLen + 3,
smallestValidMaxEncodedLen + 4,
smallestValidMaxEncodedLen + 5,
smallestValidMaxEncodedLen + 6,
smallestValidMaxEncodedLen + 7,
20,
77,
234,
512,
1999,
8192,
len(full) - 7,
len(full) - 6,
len(full) - 5,
len(full) - 4,
len(full) - 3,
len(full) - 2,
len(full) - 1,
len(full) + 0,
len(full) + 1,
len(full) + 2,
}
for _, maxEncodedLen := range maxEncodedLens {
if maxEncodedLen < smallestValidMaxEncodedLen {
continue
}
w0 := &bytes.Buffer{}
encoded := clone(full)
encLen, decLen, err := cut(w0, encoded, maxEncodedLen)
if err != nil {
tt.Errorf("f=%q, mEL=%d: cut: %v", filename, maxEncodedLen, err)
continue
}
if encLen > maxEncodedLen {
tt.Errorf("f=%q, mEL=%d: encLen vs max: got %d, want <= %d",
filename, maxEncodedLen, encLen, maxEncodedLen)
continue
}
if encLen > len(encoded) {
tt.Errorf("f=%q, mEL=%d: encLen vs len: got %d, want <= %d",
filename, maxEncodedLen, encLen, len(encoded))
continue
}
w1 := &bytes.Buffer{}
r, err := newReader(bytes.NewReader(encoded[:encLen]))
if err != nil {
tt.Errorf("f=%q, mEL=%d: newReader: %v", filename, maxEncodedLen, err)
continue
}
if n, err := io.Copy(w1, r); err != nil {
tt.Errorf("f=%q, mEL=%d: io.Copy: %v", filename, maxEncodedLen, err)
continue
} else if n != int64(decLen) {
tt.Errorf("f=%q, mEL=%d: io.Copy: got %d, want %d",
filename, maxEncodedLen, n, decLen)
continue
}
if !bytes.Equal(w0.Bytes(), w1.Bytes()) {
tt.Errorf("f=%q, mEL=%d: decoded bytes were not equal", filename, maxEncodedLen)
continue
}
if (maxEncodedLen == len(encoded)) && (int64(decLen) != fullDecodedLen) {
tt.Errorf("f=%q, mEL=%d: full decode: got %d, want %d",
filename, maxEncodedLen, decLen, fullDecodedLen)
continue
}
if err := r.Close(); err != nil {
tt.Errorf("f=%q, mEL=%d: r.Close: %v", filename, maxEncodedLen, err)
continue
}
}
}
}
func Benchmark(b *testing.B,
smallestValidMaxEncodedLen int,
cut func(io.Writer, []byte, int) (int, int, error),
newReader func(io.Reader) (io.ReadCloser, error),
filename string,
trimPrefix int,
trimSuffix int,
decodedLen int64) {
full, err := ioutil.ReadFile("../../test/data/" + filename)
if err != nil {
b.Fatalf("ReadFile: %v", err)
}
if len(full) < (trimPrefix + trimSuffix) {
b.Fatalf("len(full): got %d, want >= %d", len(full), trimPrefix+trimSuffix)
}
full = full[trimPrefix : len(full)-trimSuffix]
if n, err := calculateDecodedLen(full, newReader); err != nil {
b.Fatalf("calculateDecodedLen: %v", err)
} else if n != decodedLen {
b.Fatalf("calculateDecodedLen: got %d, want %d", n, decodedLen)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for maxEncodedLen := 10; ; maxEncodedLen *= 10 {
if maxEncodedLen < smallestValidMaxEncodedLen {
continue
}
encoded := clone(full)
if _, _, err := cut(nil, encoded, maxEncodedLen); err != nil {
b.Fatalf("cut: %v", err)
}
if maxEncodedLen >= len(full) {
break
}
}
}
}