mirror of
https://github.com/asticode/go-astikit.git
synced 2025-12-24 11:50:53 +08:00
180 lines
4.5 KiB
Go
180 lines
4.5 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)
|
|
}
|
|
}
|