// Copyright 2022 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package slicewriter import ( "io" "testing" ) func TestSliceWriter(t *testing.T) { sleq := func(t *testing.T, got []byte, want []byte) { t.Helper() if len(got) != len(want) { t.Fatalf("bad length got %d want %d", len(got), len(want)) } for i := range got { if got[i] != want[i] { t.Fatalf("bad read at %d got %d want %d", i, got[i], want[i]) } } } wf := func(t *testing.T, ws *WriteSeeker, p []byte) { t.Helper() nw, werr := ws.Write(p) if werr != nil { t.Fatalf("unexpected write error: %v", werr) } if nw != len(p) { t.Fatalf("wrong amount written want %d got %d", len(p), nw) } } rf := func(t *testing.T, ws *WriteSeeker, p []byte) { t.Helper() b := make([]byte, len(p)) nr, rerr := ws.Read(b) if rerr != nil { t.Fatalf("unexpected read error: %v", rerr) } if nr != len(p) { t.Fatalf("wrong amount read want %d got %d", len(p), nr) } sleq(t, b, p) } sk := func(t *testing.T, ws *WriteSeeker, offset int64, whence int) { t.Helper() _, err := ws.Seek(offset, whence) if err != nil { t.Fatalf("unexpected seek error: %v", err) } } wp1 := []byte{1, 2} ws := &WriteSeeker{} // write some stuff wf(t, ws, wp1) // check that BytesWritten returns what we wrote. sleq(t, ws.BytesWritten(), wp1) // offset is at end of slice, so reading should return zero bytes. rf(t, ws, []byte{}) // write some more stuff wp2 := []byte{7, 8, 9} wf(t, ws, wp2) // check that BytesWritten returns what we expect. wpex := []byte{1, 2, 7, 8, 9} sleq(t, ws.BytesWritten(), wpex) rf(t, ws, []byte{}) // seeks and reads. sk(t, ws, 1, io.SeekStart) rf(t, ws, []byte{2, 7}) sk(t, ws, -2, io.SeekCurrent) rf(t, ws, []byte{2, 7}) sk(t, ws, -4, io.SeekEnd) rf(t, ws, []byte{2, 7}) // seek back and overwrite sk(t, ws, 1, io.SeekStart) wf(t, ws, []byte{9, 11}) wpex = []byte{1, 9, 11, 8, 9} sleq(t, ws.BytesWritten(), wpex) // seeks on empty writer. ws2 := &WriteSeeker{} sk(t, ws2, 0, io.SeekStart) sk(t, ws2, 0, io.SeekCurrent) sk(t, ws2, 0, io.SeekEnd) // check for seek errors. _, err := ws.Seek(-1, io.SeekStart) if err == nil { t.Fatalf("expected error on invalid -1 seek") } _, err = ws.Seek(int64(len(ws.BytesWritten())), io.SeekStart) if err == nil { t.Fatalf("expected error on invalid %d seek", len(ws.BytesWritten())) } ws.Seek(0, io.SeekStart) _, err = ws.Seek(-1, io.SeekCurrent) if err == nil { t.Fatalf("expected error on invalid -1 seek") } _, err = ws.Seek(int64(len(ws.BytesWritten())), io.SeekCurrent) if err == nil { t.Fatalf("expected error on invalid %d seek", len(ws.BytesWritten())) } _, err = ws.Seek(1, io.SeekEnd) if err == nil { t.Fatalf("expected error on invalid 1 seek") } bsamt := int64(-1*len(ws.BytesWritten()) - 1) _, err = ws.Seek(bsamt, io.SeekEnd) if err == nil { t.Fatalf("expected error on invalid %d seek", bsamt) } // bad seek mode _, err = ws.Seek(-1, io.SeekStart+9) if err == nil { t.Fatalf("expected error on invalid seek mode") } }