mirror of
https://github.com/soypat/lneto.git
synced 2026-07-26 10:38:47 +00:00
begin adding httphi tests
This commit is contained in:
@@ -41,7 +41,7 @@ type job struct {
|
||||
}
|
||||
|
||||
type Mux interface {
|
||||
Handler(get Method, uri []byte) HandlerFunc
|
||||
LookupHandler(get Method, uri []byte) HandlerFunc
|
||||
}
|
||||
|
||||
type RouterConfig struct {
|
||||
@@ -196,7 +196,7 @@ func (r *Router) goroHandle(exch *Exchange, backoff lneto.BackoffStrategy, mux M
|
||||
// Mux URI.
|
||||
uri := reqhdr.RequestURI()
|
||||
meth := reqhdr.Method()
|
||||
handler := mux.Handler(MethodFromBytes(meth), uri)
|
||||
handler := mux.LookupHandler(MethodFromBytes(meth), uri)
|
||||
if handler != nil {
|
||||
handler(exch)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package httphi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/soypat/lneto"
|
||||
"github.com/soypat/lneto/internal"
|
||||
)
|
||||
|
||||
type rwconn struct {
|
||||
readable bytes.Buffer
|
||||
written bytes.Buffer
|
||||
closed bool
|
||||
deadline time.Time
|
||||
}
|
||||
|
||||
func (r *rwconn) Close() error {
|
||||
r.closed = true
|
||||
return nil
|
||||
}
|
||||
func (r *rwconn) Read(b []byte) (int, error) {
|
||||
if r.closed {
|
||||
return 0, net.ErrClosed
|
||||
} else if r.deadlineExceeded() {
|
||||
return 0, context.DeadlineExceeded
|
||||
}
|
||||
return r.readable.Read(b)
|
||||
}
|
||||
func (r *rwconn) Write(b []byte) (int, error) {
|
||||
if r.closed {
|
||||
return 0, net.ErrClosed
|
||||
} else if r.deadlineExceeded() {
|
||||
return 0, context.DeadlineExceeded
|
||||
}
|
||||
return r.written.Write(b)
|
||||
}
|
||||
func (r *rwconn) deadlineExceeded() bool {
|
||||
return !r.deadline.IsZero() && time.Since(r.deadline) > 0
|
||||
}
|
||||
func (r *rwconn) AddReadable(b []byte) { r.readable.Write(b) }
|
||||
func (r *rwconn) ViewWritten() []byte { return r.written.Bytes() }
|
||||
|
||||
var _ Mux = (*sliceMux)(nil)
|
||||
|
||||
type sliceMux struct {
|
||||
_handlers []struct {
|
||||
method Method
|
||||
uri string
|
||||
handler HandlerFunc
|
||||
}
|
||||
}
|
||||
|
||||
func (sm *sliceMux) LookupHandler(method Method, uri []byte) HandlerFunc {
|
||||
for _, endpoint := range sm._handlers {
|
||||
if endpoint.method != MethUndefined && endpoint.method != method {
|
||||
continue
|
||||
}
|
||||
// Method matches.
|
||||
if b2s(uri) == endpoint.uri {
|
||||
return endpoint.handler
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (sm *sliceMux) Handle(reg string, handler HandlerFunc) {
|
||||
v := internal.SliceReclaim(&sm._handlers)
|
||||
method := MethUndefined
|
||||
methodOrURL, url, methodFound := strings.Cut(reg, " ")
|
||||
if methodFound {
|
||||
method = MethodFromBytes([]byte(methodOrURL))
|
||||
} else {
|
||||
url = methodOrURL
|
||||
}
|
||||
v.method = method
|
||||
v.uri = url
|
||||
v.handler = handler
|
||||
}
|
||||
|
||||
func configSynchronousRouter(t *testing.T, router *Router, bufferSize int, mux Mux) {
|
||||
err := router.Configure(RouterConfig{
|
||||
FixedNumGoroutines: -1,
|
||||
Mux: mux,
|
||||
RequestBufferSize: bufferSize,
|
||||
ResponseMinBufferSize: bufferSize,
|
||||
Backoff: func(consecutiveBackoffs uint) (sleepOrFlag time.Duration) {
|
||||
return lneto.BackoffFlagNop
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterGet(t *testing.T) {
|
||||
const bufferSize = 1024
|
||||
|
||||
const expectResponse = "its time"
|
||||
var (
|
||||
sm sliceMux
|
||||
router Router
|
||||
conn rwconn
|
||||
)
|
||||
conn.deadline = time.Now().Add(10 * time.Millisecond) // TODO: remove after tests run without blocking forever.
|
||||
sm.Handle("GET /", staticPage(t, expectResponse))
|
||||
configSynchronousRouter(t, &router, bufferSize, &sm)
|
||||
err := router.Handle(&conn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func staticPage(t *testing.T, page string) HandlerFunc {
|
||||
return func(ex *Exchange) {
|
||||
n, err := io.WriteString(ex, page)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if n != len(page) {
|
||||
t.Fatal("expected written ", len(page), "got", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user