Files

193 lines
3.9 KiB
Go

package exiftool
import (
"io"
"runtime"
"strings"
"testing"
"testing/iotest"
)
func readAllString(t *testing.T, r io.Reader) string {
t.Helper()
var data []byte
for {
buf := make([]byte, 1024)
var n int
var err error
var memstats runtime.MemStats
runtime.ReadMemStats(&memstats)
mallocs := 0 - memstats.Mallocs
n, err = r.Read(buf)
runtime.ReadMemStats(&memstats)
mallocs += memstats.Mallocs
if mallocs > 0 {
t.Errorf("r.Read() allocs %d bytes", mallocs)
}
data = append(data, buf[:n]...)
if err != nil {
if err == io.EOF {
break
}
t.Fatalf("read failed: %v", err)
}
if n == 0 {
t.Error("read error, return 0 byte without errors")
}
}
return string(data)
}
func TestNewMarkReader(t *testing.T) {
tests := []struct {
name string
bufferSize int
mark string
wantErr string
}{
{
name: "BufferTooSmall",
bufferSize: 5,
mark: "abcd",
wantErr: "buffer too small",
},
{
name: "TwiceMarkLen",
bufferSize: 8,
mark: "abcd",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
_, err := NewMarkReader(strings.NewReader("x"), tc.bufferSize, tc.mark)
if tc.wantErr == "" {
if err != nil {
t.Fatalf("NewMarkReader() returns error: %v", err)
}
return
}
if err == nil || err.Error() != tc.wantErr {
t.Errorf("err = %v, want: %q", err, tc.wantErr)
}
})
}
}
func TestMarkReader(t *testing.T) {
tests := []struct {
name string
mark string
input string
bufferSize int
wantSegments []string
}{
{
name: "CrossRead",
mark: "<<MARK>>",
input: "hello<<MARK>>world",
bufferSize: 2 * 8, /* len(mark) = 8 */
wantSegments: []string{"hello", "world"},
},
{
name: "EndWithMark",
mark: "<<MARK>>",
input: "foo<<MARK>>bar<<MARK>>",
bufferSize: 64,
wantSegments: []string{"foo", "bar"},
},
{
name: "TrailingPrefixMark",
mark: "<<MARK>>",
input: "foo<<MARK>>bar<<MAR",
bufferSize: 64,
wantSegments: []string{"foo", "bar<<MAR"},
},
{
name: "Empty",
mark: "<<MARK>>",
input: "<<MARK>><<MARK>>abc<<MARK>>",
bufferSize: 64,
wantSegments: []string{"", "", "abc"},
},
{
name: "LongMark",
mark: "01234567890123456789",
input: "a01234567890123456789b",
bufferSize: 64,
wantSegments: []string{"a", "b"},
},
{
name: "RepeatMark",
mark: "aaaaa", /* a * 5 */
input: "0aaaaa1aaa2aaaa3aaaaa4aaaaaa5",
bufferSize: 64,
wantSegments: []string{"0", "1aaa2aaaa3", "4", "a5"},
},
{
name: "OneByteMark",
mark: "|",
input: "0|1|234|5|6",
bufferSize: 64,
wantSegments: []string{"0", "1", "234", "5", "6"},
},
}
readWraper := []struct {
name string
wrap func(r io.Reader) io.Reader
}{
{"Original", func(r io.Reader) io.Reader { return r }},
{"Half", iotest.HalfReader},
{"OneByte", iotest.OneByteReader},
}
for _, wrapper := range readWraper {
t.Run(wrapper.name, func(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
up := wrapper.wrap(strings.NewReader(tc.input))
r, err := NewMarkReader(up, tc.bufferSize, tc.mark)
if err != nil {
t.Fatal("NewMarkReader() returns error:", err)
}
for i, want := range tc.wantSegments {
if got := readAllString(t, r); got != want {
t.Errorf("segment[%d] = %q, want: %q", i, got, want)
}
var buf [1024]byte
if _, err := r.Read(buf[:]); err != io.EOF {
t.Error("r.Read() after readAllString() returns non-EOF error:", err)
}
r.Reset()
}
var buf [1024]byte
if _, err := r.Read(buf[:]); err != io.EOF {
t.Error("r.Read() after all segments returns non-EOF error:", err)
}
})
}
})
}
}