replace zxq.co/ripple/hanayo
This commit is contained in:
2
vendor/github.com/valyala/fasthttp/fasthttputil/doc.go
generated
vendored
Normal file
2
vendor/github.com/valyala/fasthttp/fasthttputil/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package fasthttputil provides utility functions for fasthttp.
|
||||
package fasthttputil
|
84
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go
generated
vendored
Normal file
84
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package fasthttputil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// InmemoryListener provides in-memory dialer<->net.Listener implementation.
|
||||
//
|
||||
// It may be used either for fast in-process client<->server communcations
|
||||
// without network stack overhead or for client<->server tests.
|
||||
type InmemoryListener struct {
|
||||
lock sync.Mutex
|
||||
closed bool
|
||||
conns chan net.Conn
|
||||
}
|
||||
|
||||
// NewInmemoryListener returns new in-memory dialer<->net.Listener.
|
||||
func NewInmemoryListener() *InmemoryListener {
|
||||
return &InmemoryListener{
|
||||
conns: make(chan net.Conn, 1024),
|
||||
}
|
||||
}
|
||||
|
||||
// Accept implements net.Listener's Accept.
|
||||
//
|
||||
// It is safe calling Accept from concurrently running goroutines.
|
||||
//
|
||||
// Accept returns new connection per each Dial call.
|
||||
func (ln *InmemoryListener) Accept() (net.Conn, error) {
|
||||
c, ok := <-ln.conns
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("InmemoryListener is already closed: use of closed network connection")
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close implements net.Listener's Close.
|
||||
func (ln *InmemoryListener) Close() error {
|
||||
var err error
|
||||
|
||||
ln.lock.Lock()
|
||||
if !ln.closed {
|
||||
close(ln.conns)
|
||||
ln.closed = true
|
||||
} else {
|
||||
err = fmt.Errorf("InmemoryListener is already closed")
|
||||
}
|
||||
ln.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Addr implements net.Listener's Addr.
|
||||
func (ln *InmemoryListener) Addr() net.Addr {
|
||||
return &net.UnixAddr{
|
||||
Name: "InmemoryListener",
|
||||
Net: "memory",
|
||||
}
|
||||
}
|
||||
|
||||
// Dial creates new client<->server connection, enqueues server side
|
||||
// of the connection to Accept and returns client side of the connection.
|
||||
//
|
||||
// It is safe calling Dial from concurrently running goroutines.
|
||||
func (ln *InmemoryListener) Dial() (net.Conn, error) {
|
||||
pc := NewPipeConns()
|
||||
cConn := pc.Conn1()
|
||||
sConn := pc.Conn2()
|
||||
ln.lock.Lock()
|
||||
if !ln.closed {
|
||||
ln.conns <- sConn
|
||||
} else {
|
||||
sConn.Close()
|
||||
cConn.Close()
|
||||
cConn = nil
|
||||
}
|
||||
ln.lock.Unlock()
|
||||
|
||||
if cConn == nil {
|
||||
return nil, fmt.Errorf("InmemoryListener is already closed")
|
||||
}
|
||||
return cConn, nil
|
||||
}
|
92
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener_test.go
generated
vendored
Normal file
92
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener_test.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package fasthttputil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInmemoryListener(t *testing.T) {
|
||||
ln := NewInmemoryListener()
|
||||
|
||||
ch := make(chan struct{})
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
conn, err := ln.Dial()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
req := fmt.Sprintf("request_%d", n)
|
||||
nn, err := conn.Write([]byte(req))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if nn != len(req) {
|
||||
t.Fatalf("unexpected number of bytes written: %d. Expecting %d", nn, len(req))
|
||||
}
|
||||
buf := make([]byte, 30)
|
||||
nn, err = conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
buf = buf[:nn]
|
||||
resp := fmt.Sprintf("response_%d", n)
|
||||
if nn != len(resp) {
|
||||
t.Fatalf("unexpected number of bytes read: %d. Expecting %d", nn, len(resp))
|
||||
}
|
||||
if string(buf) != resp {
|
||||
t.Fatalf("unexpected response %q. Expecting %q", buf, resp)
|
||||
}
|
||||
ch <- struct{}{}
|
||||
}(i)
|
||||
}
|
||||
|
||||
serverCh := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
close(serverCh)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
buf := make([]byte, 30)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
buf = buf[:n]
|
||||
if !bytes.HasPrefix(buf, []byte("request_")) {
|
||||
t.Fatalf("unexpected request prefix %q. Expecting %q", buf, "request_")
|
||||
}
|
||||
resp := fmt.Sprintf("response_%s", buf[len("request_"):])
|
||||
n, err = conn.Write([]byte(resp))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if n != len(resp) {
|
||||
t.Fatalf("unexpected number of bytes written: %d. Expecting %d", n, len(resp))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
if err := ln.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-serverCh:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
108
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener_timing_test.go
generated
vendored
Normal file
108
vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener_timing_test.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package fasthttputil_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/valyala/fasthttp/fasthttputil"
|
||||
)
|
||||
|
||||
// BenchmarkPlainStreaming measures end-to-end plaintext streaming performance
|
||||
// for fasthttp client and server.
|
||||
//
|
||||
// It issues http requests over a small number of keep-alive connections.
|
||||
func BenchmarkPlainStreaming(b *testing.B) {
|
||||
benchmark(b, streamingHandler, false)
|
||||
}
|
||||
|
||||
// BenchmarkPlainHandshake measures end-to-end plaintext handshake performance
|
||||
// for fasthttp client and server.
|
||||
//
|
||||
// It re-establishes new connection per each http request.
|
||||
func BenchmarkPlainHandshake(b *testing.B) {
|
||||
benchmark(b, handshakeHandler, false)
|
||||
}
|
||||
|
||||
// BenchmarkTLSStreaming measures end-to-end TLS streaming performance
|
||||
// for fasthttp client and server.
|
||||
//
|
||||
// It issues http requests over a small number of TLS keep-alive connections.
|
||||
func BenchmarkTLSStreaming(b *testing.B) {
|
||||
benchmark(b, streamingHandler, true)
|
||||
}
|
||||
|
||||
// BenchmarkTLSHandshake measures end-to-end TLS handshake performance
|
||||
// for fasthttp client and server.
|
||||
//
|
||||
// It re-establishes new TLS connection per each http request.
|
||||
func BenchmarkTLSHandshake(b *testing.B) {
|
||||
benchmark(b, handshakeHandler, true)
|
||||
}
|
||||
|
||||
func benchmark(b *testing.B, h fasthttp.RequestHandler, isTLS bool) {
|
||||
ln := fasthttputil.NewInmemoryListener()
|
||||
serverStopCh := startServer(b, ln, h, isTLS)
|
||||
c := newClient(ln, isTLS)
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
runRequests(b, pb, c)
|
||||
})
|
||||
ln.Close()
|
||||
<-serverStopCh
|
||||
}
|
||||
|
||||
func streamingHandler(ctx *fasthttp.RequestCtx) {
|
||||
ctx.WriteString("foobar")
|
||||
}
|
||||
|
||||
func handshakeHandler(ctx *fasthttp.RequestCtx) {
|
||||
streamingHandler(ctx)
|
||||
|
||||
// Explicitly close connection after each response.
|
||||
ctx.SetConnectionClose()
|
||||
}
|
||||
|
||||
func startServer(b *testing.B, ln *fasthttputil.InmemoryListener, h fasthttp.RequestHandler, isTLS bool) <-chan struct{} {
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
var err error
|
||||
if isTLS {
|
||||
err = fasthttp.ServeTLS(ln, certFile, keyFile, h)
|
||||
} else {
|
||||
err = fasthttp.Serve(ln, h)
|
||||
}
|
||||
if err != nil {
|
||||
b.Fatalf("unexpected error in server: %s", err)
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
const (
|
||||
certFile = "./ssl-cert-snakeoil.pem"
|
||||
keyFile = "./ssl-cert-snakeoil.key"
|
||||
)
|
||||
|
||||
func newClient(ln *fasthttputil.InmemoryListener, isTLS bool) *fasthttp.HostClient {
|
||||
return &fasthttp.HostClient{
|
||||
Dial: func(addr string) (net.Conn, error) {
|
||||
return ln.Dial()
|
||||
},
|
||||
IsTLS: isTLS,
|
||||
}
|
||||
}
|
||||
|
||||
func runRequests(b *testing.B, pb *testing.PB, c *fasthttp.HostClient) {
|
||||
var req fasthttp.Request
|
||||
req.SetRequestURI("http://foo.bar/baz")
|
||||
var resp fasthttp.Response
|
||||
for pb.Next() {
|
||||
if err := c.Do(&req, &resp); err != nil {
|
||||
b.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if resp.StatusCode() != fasthttp.StatusOK {
|
||||
b.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode(), fasthttp.StatusOK)
|
||||
}
|
||||
}
|
||||
}
|
221
vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go
generated
vendored
Normal file
221
vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
package fasthttputil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewPipeConns returns new bi-directonal connection pipe.
|
||||
func NewPipeConns() *PipeConns {
|
||||
ch1 := make(chan *byteBuffer, 4)
|
||||
ch2 := make(chan *byteBuffer, 4)
|
||||
|
||||
pc := &PipeConns{
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
pc.c1.rCh = ch1
|
||||
pc.c1.wCh = ch2
|
||||
pc.c2.rCh = ch2
|
||||
pc.c2.wCh = ch1
|
||||
pc.c1.pc = pc
|
||||
pc.c2.pc = pc
|
||||
return pc
|
||||
}
|
||||
|
||||
// PipeConns provides bi-directional connection pipe,
|
||||
// which use in-process memory as a transport.
|
||||
//
|
||||
// PipeConns must be created by calling NewPipeConns.
|
||||
//
|
||||
// PipeConns has the following additional features comparing to connections
|
||||
// returned from net.Pipe():
|
||||
//
|
||||
// * It is faster.
|
||||
// * It buffers Write calls, so there is no need to have concurrent goroutine
|
||||
// calling Read in order to unblock each Write call.
|
||||
type PipeConns struct {
|
||||
c1 pipeConn
|
||||
c2 pipeConn
|
||||
stopCh chan struct{}
|
||||
stopChLock sync.Mutex
|
||||
}
|
||||
|
||||
// Conn1 returns the first end of bi-directional pipe.
|
||||
//
|
||||
// Data written to Conn1 may be read from Conn2.
|
||||
// Data written to Conn2 may be read from Conn1.
|
||||
func (pc *PipeConns) Conn1() net.Conn {
|
||||
return &pc.c1
|
||||
}
|
||||
|
||||
// Conn2 returns the second end of bi-directional pipe.
|
||||
//
|
||||
// Data written to Conn2 may be read from Conn1.
|
||||
// Data written to Conn1 may be read from Conn2.
|
||||
func (pc *PipeConns) Conn2() net.Conn {
|
||||
return &pc.c2
|
||||
}
|
||||
|
||||
// Close closes pipe connections.
|
||||
func (pc *PipeConns) Close() error {
|
||||
pc.stopChLock.Lock()
|
||||
select {
|
||||
case <-pc.stopCh:
|
||||
default:
|
||||
close(pc.stopCh)
|
||||
}
|
||||
pc.stopChLock.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type pipeConn struct {
|
||||
b *byteBuffer
|
||||
bb []byte
|
||||
|
||||
rCh chan *byteBuffer
|
||||
wCh chan *byteBuffer
|
||||
pc *PipeConns
|
||||
}
|
||||
|
||||
func (c *pipeConn) Write(p []byte) (int, error) {
|
||||
b := acquireByteBuffer()
|
||||
b.b = append(b.b[:0], p...)
|
||||
|
||||
select {
|
||||
case <-c.pc.stopCh:
|
||||
releaseByteBuffer(b)
|
||||
return 0, errConnectionClosed
|
||||
default:
|
||||
}
|
||||
|
||||
select {
|
||||
case c.wCh <- b:
|
||||
default:
|
||||
select {
|
||||
case c.wCh <- b:
|
||||
case <-c.pc.stopCh:
|
||||
releaseByteBuffer(b)
|
||||
return 0, errConnectionClosed
|
||||
}
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (c *pipeConn) Read(p []byte) (int, error) {
|
||||
mayBlock := true
|
||||
nn := 0
|
||||
for len(p) > 0 {
|
||||
n, err := c.read(p, mayBlock)
|
||||
nn += n
|
||||
if err != nil {
|
||||
if !mayBlock && err == errWouldBlock {
|
||||
err = nil
|
||||
}
|
||||
return nn, err
|
||||
}
|
||||
p = p[n:]
|
||||
mayBlock = false
|
||||
}
|
||||
|
||||
return nn, nil
|
||||
}
|
||||
|
||||
func (c *pipeConn) read(p []byte, mayBlock bool) (int, error) {
|
||||
if len(c.bb) == 0 {
|
||||
if err := c.readNextByteBuffer(mayBlock); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
n := copy(p, c.bb)
|
||||
c.bb = c.bb[n:]
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (c *pipeConn) readNextByteBuffer(mayBlock bool) error {
|
||||
releaseByteBuffer(c.b)
|
||||
c.b = nil
|
||||
|
||||
select {
|
||||
case c.b = <-c.rCh:
|
||||
default:
|
||||
if !mayBlock {
|
||||
return errWouldBlock
|
||||
}
|
||||
select {
|
||||
case c.b = <-c.rCh:
|
||||
case <-c.pc.stopCh:
|
||||
return io.EOF
|
||||
}
|
||||
}
|
||||
|
||||
c.bb = c.b.b
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
errWouldBlock = errors.New("would block")
|
||||
errConnectionClosed = errors.New("connection closed")
|
||||
errNoDeadlines = errors.New("deadline not supported")
|
||||
)
|
||||
|
||||
func (c *pipeConn) Close() error {
|
||||
return c.pc.Close()
|
||||
}
|
||||
|
||||
func (c *pipeConn) LocalAddr() net.Addr {
|
||||
return pipeAddr(0)
|
||||
}
|
||||
|
||||
func (c *pipeConn) RemoteAddr() net.Addr {
|
||||
return pipeAddr(0)
|
||||
}
|
||||
|
||||
func (c *pipeConn) SetDeadline(t time.Time) error {
|
||||
return errNoDeadlines
|
||||
}
|
||||
|
||||
func (c *pipeConn) SetReadDeadline(t time.Time) error {
|
||||
return c.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *pipeConn) SetWriteDeadline(t time.Time) error {
|
||||
return c.SetDeadline(t)
|
||||
}
|
||||
|
||||
type pipeAddr int
|
||||
|
||||
func (pipeAddr) Network() string {
|
||||
return "pipe"
|
||||
}
|
||||
|
||||
func (pipeAddr) String() string {
|
||||
return "pipe"
|
||||
}
|
||||
|
||||
type byteBuffer struct {
|
||||
b []byte
|
||||
}
|
||||
|
||||
func acquireByteBuffer() *byteBuffer {
|
||||
return byteBufferPool.Get().(*byteBuffer)
|
||||
}
|
||||
|
||||
func releaseByteBuffer(b *byteBuffer) {
|
||||
if b != nil {
|
||||
byteBufferPool.Put(b)
|
||||
}
|
||||
}
|
||||
|
||||
var byteBufferPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &byteBuffer{
|
||||
b: make([]byte, 1024),
|
||||
}
|
||||
},
|
||||
}
|
236
vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns_test.go
generated
vendored
Normal file
236
vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns_test.go
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
package fasthttputil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPipeConnsCloseWhileReadWriteConcurrent(t *testing.T) {
|
||||
concurrency := 4
|
||||
ch := make(chan struct{}, concurrency)
|
||||
for i := 0; i < concurrency; i++ {
|
||||
go func() {
|
||||
testPipeConnsCloseWhileReadWriteSerial(t)
|
||||
ch <- struct{}{}
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < concurrency; i++ {
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeConnsCloseWhileReadWriteSerial(t *testing.T) {
|
||||
testPipeConnsCloseWhileReadWriteSerial(t)
|
||||
}
|
||||
|
||||
func testPipeConnsCloseWhileReadWriteSerial(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
testPipeConnsCloseWhileReadWrite(t)
|
||||
}
|
||||
}
|
||||
|
||||
func testPipeConnsCloseWhileReadWrite(t *testing.T) {
|
||||
pc := NewPipeConns()
|
||||
c1 := pc.Conn1()
|
||||
c2 := pc.Conn2()
|
||||
|
||||
readCh := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
if _, err = io.Copy(ioutil.Discard, c1); err != nil {
|
||||
if err != errConnectionClosed {
|
||||
err = fmt.Errorf("unexpected error: %s", err)
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
readCh <- err
|
||||
}()
|
||||
|
||||
writeCh := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
for {
|
||||
if _, err = c2.Write([]byte("foobar")); err != nil {
|
||||
if err != errConnectionClosed {
|
||||
err = fmt.Errorf("unexpected error: %s", err)
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
writeCh <- err
|
||||
}()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
if err := c1.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := c2.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case err := <-readCh:
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error in reader: %s", err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
select {
|
||||
case err := <-writeCh:
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error in writer: %s", err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeConnsReadWriteSerial(t *testing.T) {
|
||||
testPipeConnsReadWriteSerial(t)
|
||||
}
|
||||
|
||||
func TestPipeConnsReadWriteConcurrent(t *testing.T) {
|
||||
testConcurrency(t, 10, testPipeConnsReadWriteSerial)
|
||||
}
|
||||
|
||||
func testPipeConnsReadWriteSerial(t *testing.T) {
|
||||
pc := NewPipeConns()
|
||||
testPipeConnsReadWrite(t, pc.Conn1(), pc.Conn2())
|
||||
|
||||
pc = NewPipeConns()
|
||||
testPipeConnsReadWrite(t, pc.Conn2(), pc.Conn1())
|
||||
}
|
||||
|
||||
func testPipeConnsReadWrite(t *testing.T, c1, c2 net.Conn) {
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
var buf [32]byte
|
||||
for i := 0; i < 10; i++ {
|
||||
// The first write
|
||||
s1 := fmt.Sprintf("foo_%d", i)
|
||||
n, err := c1.Write([]byte(s1))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if n != len(s1) {
|
||||
t.Fatalf("unexpected number of bytes written: %d. Expecting %d", n, len(s1))
|
||||
}
|
||||
|
||||
// The second write
|
||||
s2 := fmt.Sprintf("bar_%d", i)
|
||||
n, err = c1.Write([]byte(s2))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if n != len(s2) {
|
||||
t.Fatalf("unexpected number of bytes written: %d. Expecting %d", n, len(s2))
|
||||
}
|
||||
|
||||
// Read data written above in two writes
|
||||
s := s1 + s2
|
||||
n, err = c2.Read(buf[:])
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if n != len(s) {
|
||||
t.Fatalf("unexpected number of bytes read: %d. Expecting %d", n, len(s))
|
||||
}
|
||||
if string(buf[:n]) != s {
|
||||
t.Fatalf("unexpected string read: %q. Expecting %q", buf[:n], s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipeConnsCloseSerial(t *testing.T) {
|
||||
testPipeConnsCloseSerial(t)
|
||||
}
|
||||
|
||||
func TestPipeConnsCloseConcurrent(t *testing.T) {
|
||||
testConcurrency(t, 10, testPipeConnsCloseSerial)
|
||||
}
|
||||
|
||||
func testPipeConnsCloseSerial(t *testing.T) {
|
||||
pc := NewPipeConns()
|
||||
testPipeConnsClose(t, pc.Conn1(), pc.Conn2())
|
||||
|
||||
pc = NewPipeConns()
|
||||
testPipeConnsClose(t, pc.Conn2(), pc.Conn1())
|
||||
}
|
||||
|
||||
func testPipeConnsClose(t *testing.T, c1, c2 net.Conn) {
|
||||
if err := c1.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
var buf [10]byte
|
||||
|
||||
// attempt writing to closed conn
|
||||
for i := 0; i < 10; i++ {
|
||||
n, err := c1.Write(buf[:])
|
||||
if err == nil {
|
||||
t.Fatalf("expecting error")
|
||||
}
|
||||
if n != 0 {
|
||||
t.Fatalf("unexpected number of bytes written: %d. Expecting 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
// attempt reading from closed conn
|
||||
for i := 0; i < 10; i++ {
|
||||
n, err := c2.Read(buf[:])
|
||||
if err == nil {
|
||||
t.Fatalf("expecting error")
|
||||
}
|
||||
if err != io.EOF {
|
||||
t.Fatalf("unexpected error: %s. Expecting %s", err, io.EOF)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Fatalf("unexpected number of bytes read: %d. Expecting 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c2.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
// attempt closing already closed conns
|
||||
for i := 0; i < 10; i++ {
|
||||
if err := c1.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := c2.Close(); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testConcurrency(t *testing.T, concurrency int, f func(*testing.T)) {
|
||||
ch := make(chan struct{}, concurrency)
|
||||
for i := 0; i < concurrency; i++ {
|
||||
go func() {
|
||||
f(t)
|
||||
ch <- struct{}{}
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < concurrency; i++ {
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
}
|
28
vendor/github.com/valyala/fasthttp/fasthttputil/ssl-cert-snakeoil.key
generated
vendored
Normal file
28
vendor/github.com/valyala/fasthttp/fasthttputil/ssl-cert-snakeoil.key
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD4IQusAs8PJdnG
|
||||
3mURt/AXtgC+ceqLOatJ49JJE1VPTkMAy+oE1f1XvkMrYsHqmDf6GWVzgVXryL4U
|
||||
wq2/nJSm56ddhN55nI8oSN3dtywUB8/ShelEN73nlN77PeD9tl6NksPwWaKrqxq0
|
||||
FlabRPZSQCfmgZbhDV8Sa8mfCkFU0G0lit6kLGceCKMvmW+9Bz7ebsYmVdmVMxmf
|
||||
IJStFD44lWFTdUc65WISKEdW2ELcUefb0zOLw+0PCbXFGJH5x5ktksW8+BBk2Hkg
|
||||
GeQRL/qPCccthbScO0VgNj3zJ3ZZL0ObSDAbvNDG85joeNjDNq5DT/BAZ0bOSbEF
|
||||
sh+f9BAzAgMBAAECggEBAJWv2cq7Jw6MVwSRxYca38xuD6TUNBopgBvjREixURW2
|
||||
sNUaLuMb9Omp7fuOaE2N5rcJ+xnjPGIxh/oeN5MQctz9gwn3zf6vY+15h97pUb4D
|
||||
uGvYPRDaT8YVGS+X9NMZ4ZCmqW2lpWzKnCFoGHcy8yZLbcaxBsRdvKzwOYGoPiFb
|
||||
K2QuhXZ/1UPmqK9i2DFKtj40X6vBszTNboFxOVpXrPu0FJwLVSDf2hSZ4fMM0DH3
|
||||
YqwKcYf5te+hxGKgrqRA3tn0NCWii0in6QIwXMC+kMw1ebg/tZKqyDLMNptAK8J+
|
||||
DVw9m5X1seUHS5ehU/g2jrQrtK5WYn7MrFK4lBzlRwECgYEA/d1TeANYECDWRRDk
|
||||
B0aaRZs87Rwl/J9PsvbsKvtU/bX+OfSOUjOa9iQBqn0LmU8GqusEET/QVUfocVwV
|
||||
Bggf/5qDLxz100Rj0ags/yE/kNr0Bb31kkkKHFMnCT06YasR7qKllwrAlPJvQv9x
|
||||
IzBKq+T/Dx08Wep9bCRSFhzRCnsCgYEA+jdeZXTDr/Vz+D2B3nAw1frqYFfGnEVY
|
||||
wqmoK3VXMDkGuxsloO2rN+SyiUo3JNiQNPDub/t7175GH5pmKtZOlftePANsUjBj
|
||||
wZ1D0rI5Bxu/71ibIUYIRVmXsTEQkh/ozoh3jXCZ9+bLgYiYx7789IUZZSokFQ3D
|
||||
FICUT9KJ36kCgYAGoq9Y1rWJjmIrYfqj2guUQC+CfxbbGIrrwZqAsRsSmpwvhZ3m
|
||||
tiSZxG0quKQB+NfSxdvQW5ulbwC7Xc3K35F+i9pb8+TVBdeaFkw+yu6vaZmxQLrX
|
||||
fQM/pEjD7A7HmMIaO7QaU5SfEAsqdCTP56Y8AftMuNXn/8IRfo2KuGwaWwKBgFpU
|
||||
ILzJoVdlad9E/Rw7LjYhZfkv1uBVXIyxyKcfrkEXZSmozDXDdxsvcZCEfVHM6Ipk
|
||||
K/+7LuMcqp4AFEAEq8wTOdq6daFaHLkpt/FZK6M4TlruhtpFOPkoNc3e45eM83OT
|
||||
6mziKINJC1CQ6m65sQHpBtjxlKMRG8rL/D6wx9s5AoGBAMRlqNPMwglT3hvDmsAt
|
||||
9Lf9pdmhERUlHhD8bj8mDaBj2Aqv7f6VRJaYZqP403pKKQexuqcn80mtjkSAPFkN
|
||||
Cj7BVt/RXm5uoxDTnfi26RF9F6yNDEJ7UU9+peBr99aazF/fTgW/1GcMkQnum8uV
|
||||
c257YgaWmjK9uB0Y2r2VxS0G
|
||||
-----END PRIVATE KEY-----
|
17
vendor/github.com/valyala/fasthttp/fasthttputil/ssl-cert-snakeoil.pem
generated
vendored
Normal file
17
vendor/github.com/valyala/fasthttp/fasthttputil/ssl-cert-snakeoil.pem
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICujCCAaKgAwIBAgIJAMbXnKZ/cikUMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
|
||||
BAMTCnVidW50dS5uYW4wHhcNMTUwMjA0MDgwMTM5WhcNMjUwMjAxMDgwMTM5WjAV
|
||||
MRMwEQYDVQQDEwp1YnVudHUubmFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEA+CELrALPDyXZxt5lEbfwF7YAvnHqizmrSePSSRNVT05DAMvqBNX9V75D
|
||||
K2LB6pg3+hllc4FV68i+FMKtv5yUpuenXYTeeZyPKEjd3bcsFAfP0oXpRDe955Te
|
||||
+z3g/bZejZLD8Fmiq6satBZWm0T2UkAn5oGW4Q1fEmvJnwpBVNBtJYrepCxnHgij
|
||||
L5lvvQc+3m7GJlXZlTMZnyCUrRQ+OJVhU3VHOuViEihHVthC3FHn29Mzi8PtDwm1
|
||||
xRiR+ceZLZLFvPgQZNh5IBnkES/6jwnHLYW0nDtFYDY98yd2WS9Dm0gwG7zQxvOY
|
||||
6HjYwzauQ0/wQGdGzkmxBbIfn/QQMwIDAQABow0wCzAJBgNVHRMEAjAAMA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQBQjKm/4KN/iTgXbLTL3i7zaxYXFLXsnT1tF+ay4VA8aj98
|
||||
L3JwRTciZ3A5iy/W4VSCt3eASwOaPWHKqDBB5RTtL73LoAqsWmO3APOGQAbixcQ2
|
||||
45GXi05OKeyiYRi1Nvq7Unv9jUkRDHUYVPZVSAjCpsXzPhFkmZoTRxmx5l0ZF7Li
|
||||
K91lI5h+eFq0dwZwrmlPambyh1vQUi70VHv8DNToVU29kel7YLbxGbuqETfhrcy6
|
||||
X+Mha6RYITkAn5FqsZcKMsc9eYGEF4l3XV+oS7q6xfTxktYJMFTI18J0lQ2Lv/CI
|
||||
whdMnYGntDQBE/iFCrJEGNsKGc38796GBOb5j+zd
|
||||
-----END CERTIFICATE-----
|
Reference in New Issue
Block a user