Files
2026-03-13 09:59:31 +00:00

223 lines
5.4 KiB
Go

package astikit
import (
"bytes"
"context"
"errors"
"io"
"reflect"
"testing"
"time"
)
func TestCopy(t *testing.T) {
// Context canceled
ctx, cancel := context.WithCancel(context.Background())
cancel()
r, w := bytes.NewBuffer([]byte("bla bla bla")), &bytes.Buffer{}
n, err := Copy(ctx, w, r)
if e := int64(0); n != e {
t.Fatalf("expected %v, got %v", e, n)
}
if e := context.Canceled; !errors.Is(err, e) {
t.Fatalf("error should be %+v, got %+v", e, err)
}
// Default
n, err = Copy(context.Background(), w, r)
if e := int64(11); n != e {
t.Fatalf("expected %v, got %v", e, n)
}
if err != nil {
t.Fatalf("expected no error, got %+v", err)
}
}
func TestWriterAdapter(t *testing.T) {
// Init
var o []string
var w = NewWriterAdapter(WriterAdapterOptions{
Callback: func(i []byte) {
o = append(o, string(i))
},
Split: []byte("\n"),
})
// No Split
w.Write([]byte("bla bla ")) //nolint:errcheck
if len(o) != 0 {
t.Fatalf("expected %v, got %v", 0, len(o))
}
// Multi Split
w.Write([]byte("bla \nbla bla\nbla")) //nolint:errcheck
if e := []string{"bla bla bla ", "bla bla"}; !reflect.DeepEqual(o, e) {
t.Fatalf("expected %+v, got %+v", e, o)
}
// Close
w.Close()
if e := []string{"bla bla bla ", "bla bla", "bla"}; !reflect.DeepEqual(o, e) {
t.Fatalf("expected %+v, got %+v", e, o)
}
}
func TestPiper(t *testing.T) {
p1 := NewPiper(PiperOptions{})
defer p1.Close()
// Piper shouldn't block on write
w := []byte("test")
ctx1, cancel1 := context.WithTimeout(context.Background(), time.Second)
defer cancel1()
var n int
var err error
go func() {
defer cancel1()
n, err = p1.Write(w)
}()
<-ctx1.Done()
if errCtx := ctx1.Err(); errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected no deadline exceeded error, got %+v", errCtx)
}
if err != nil {
t.Fatalf("expected no error, got %+v", err)
}
if e, g := 4, n; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
r := make([]byte, 10)
n, err = p1.Read(r)
if err != nil {
t.Fatalf("expected no error, got %+v", err)
}
if e, g := 4, n; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
if e, g := w, r[:n]; !bytes.Equal(e, g) {
t.Fatalf("expected %s, got %s", e, g)
}
// Piper should block on read unless write or piper is closed
ctx2, cancel2 := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel2()
ctx3, cancel3 := context.WithTimeout(context.Background(), time.Second)
defer cancel3()
r = make([]byte, 10)
go func() {
defer cancel2()
defer cancel3()
n, err = p1.Read(r)
}()
<-ctx2.Done()
if errCtx := ctx2.Err(); !errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected deadline exceeded error, got %+v", errCtx)
}
_, errWrite := p1.Write(w)
if errWrite != nil {
t.Fatalf("expected no error, got %+v", errWrite)
}
<-ctx3.Done()
if errCtx := ctx3.Err(); errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected no deadline exceeded error, got %+v", errCtx)
}
if err != nil {
t.Fatalf("expected no error, got %+v", err)
}
if e, g := 4, n; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
if e, g := w, r[:n]; !bytes.Equal(e, g) {
t.Fatalf("expected %s, got %s", e, g)
}
ctx4, cancel4 := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel4()
ctx5, cancel5 := context.WithTimeout(context.Background(), time.Second)
defer cancel5()
go func() {
defer cancel4()
defer cancel5()
_, err = p1.Read(r)
}()
<-ctx4.Done()
if errCtx := ctx4.Err(); !errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected deadline exceeded error, got %+v", errCtx)
}
p1.Close()
<-ctx5.Done()
if errCtx := ctx5.Err(); errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected no deadline exceeded error, got %+v", errCtx)
}
if !errors.Is(err, io.EOF) {
t.Fatalf("expected io.EOF error, got %+v", err)
}
_, err = p1.Write(w)
if !errors.Is(err, io.EOF) {
t.Fatalf("expected io.EOF error, got %+v", err)
}
// Piper should timeout on read if a read timeout is provided
e1 := errors.New("1")
p2 := NewPiper(PiperOptions{
ReadTimeout: time.Millisecond,
ReadTimeoutError: e1,
})
defer p2.Close()
ctx6, cancel6 := context.WithTimeout(context.Background(), time.Second)
defer cancel6()
go func() {
defer cancel6()
_, err = p2.Read(r)
}()
<-ctx6.Done()
if errCtx := ctx6.Err(); errors.Is(errCtx, context.DeadlineExceeded) {
t.Fatalf("expected no deadline exceeded error, got %+v", errCtx)
}
if !errors.Is(err, e1) {
t.Fatalf("expected %s, got %s", e1, err)
}
}
type mockedWriter struct {
b []byte
err error
}
func (w *mockedWriter) Write(b []byte) (int, error) {
if w.err != nil {
return 0, w.err
}
w.b = append(w.b, b...)
return len(b), nil
}
func TestWriteChainer(t *testing.T) {
w := &mockedWriter{}
c := NewWriteChainer(w)
n, err := c.Write(
WriteWithLabel("1", []byte("1")),
WriteWithCondition("2", []byte("2"), false),
WriteWithCondition("3", []byte("3"), true),
)
if err != nil {
t.Fatalf("expected no error, got %+v", err)
}
if e, g := 2, n; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
if e, g := "13", string(w.b); e != g {
t.Fatalf("expected %s, got %s", e, g)
}
w.err = errors.New("test")
n, err = c.Write(WriteWithLabel("label", []byte("4")))
if err == nil {
t.Fatal("expected error, got nil")
}
if e, g := "astikit: writing label failed: test", err.Error(); e != g {
t.Fatalf("expected %s, got %s", e, g)
}
if e, g := 0, n; e != g {
t.Fatalf("expected %d, got %d", e, g)
}
}