Added more tests

This commit is contained in:
Eduard Urbach 2024-03-28 14:27:40 +01:00
parent 805f92468a
commit 5af7efcdbd
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
3 changed files with 149 additions and 31 deletions

View File

@ -54,8 +54,13 @@ PASS: TestResponseHeader
PASS: TestResponseHeaderOverwrite PASS: TestResponseHeaderOverwrite
PASS: TestPanic PASS: TestPanic
PASS: TestRun PASS: TestRun
PASS: TestBadRequest
PASS: TestBadRequestHeader
PASS: TestBadRequestMethod
PASS: TestBadRequestProtocol
PASS: TestEarlyClose
PASS: TestUnavailablePort PASS: TestUnavailablePort
coverage: 95.5% of statements coverage: 100.0% of statements
``` ```
## Benchmarks ## Benchmarks

View File

@ -128,8 +128,7 @@ func (s *server) handleConnection(conn net.Conn) {
defer s.contextPool.Put(ctx) defer s.contextPool.Put(ctx)
for { for {
// Search for a line containing HTTP method and url // Read the HTTP request line
for {
message, err := ctx.reader.ReadString('\n') message, err := ctx.reader.ReadString('\n')
if err != nil { if err != nil {
@ -139,28 +138,28 @@ func (s *server) handleConnection(conn net.Conn) {
space := strings.IndexByte(message, ' ') space := strings.IndexByte(message, ' ')
if space <= 0 { if space <= 0 {
continue fmt.Fprint(conn, "HTTP/1.1 400 Bad Request\r\n\r\n")
return
} }
method = message[:space] method = message[:space]
if !isRequestMethod(method) { if !isRequestMethod(method) {
continue fmt.Fprint(conn, "HTTP/1.1 400 Bad Request\r\n\r\n")
return
} }
lastSpace := strings.LastIndexByte(message, ' ') lastSpace := strings.LastIndexByte(message, ' ')
if lastSpace == -1 { if lastSpace == space {
lastSpace = len(message) lastSpace = len(message) - len("\r\n")
} }
url = message[space+1 : lastSpace] url = message[space+1 : lastSpace]
break
}
// Add headers until we meet an empty line // Add headers until we meet an empty line
for { for {
message, err := ctx.reader.ReadString('\n') message, err = ctx.reader.ReadString('\n')
if err != nil { if err != nil {
return return
@ -210,7 +209,7 @@ func (s *server) handleRequest(ctx *context, method string, url string, writer i
s.errorHandler(ctx, err) s.errorHandler(ctx, err)
} }
fmt.Fprintf(writer, "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n%s\r\n%s", ctx.status, "OK", len(ctx.response.body), ctx.response.headerText(), ctx.response.body) fmt.Fprintf(writer, "HTTP/1.1 %d\r\nContent-Length: %d\r\n%s\r\n%s", ctx.status, len(ctx.response.body), ctx.response.headerText(), ctx.response.body)
} }
// newContext allocates a new context with the default state. // newContext allocates a new context with the default state.

View File

@ -1,6 +1,7 @@
package web_test package web_test
import ( import (
"io"
"net" "net"
"net/http" "net/http"
"syscall" "syscall"
@ -32,9 +33,122 @@ func TestRun(t *testing.T) {
s := web.NewServer() s := web.NewServer()
go func() { go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
_, err := http.Get("http://127.0.0.1:8080/") _, err := http.Get("http://127.0.0.1:8080/")
assert.Nil(t, err) assert.Nil(t, err)
err = syscall.Kill(syscall.Getpid(), syscall.SIGTERM) }()
s.Run(":8080")
}
func TestBadRequest(t *testing.T) {
s := web.NewServer()
go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
conn, err := net.Dial("tcp", ":8080")
assert.Nil(t, err)
defer conn.Close()
_, err = io.WriteString(conn, "BadRequest\r\n\r\n")
assert.Nil(t, err)
response, err := io.ReadAll(conn)
assert.Nil(t, err)
assert.Equal(t, string(response), "HTTP/1.1 400 Bad Request\r\n\r\n")
}()
s.Run(":8080")
}
func TestBadRequestHeader(t *testing.T) {
s := web.NewServer()
s.Get("/", func(ctx web.Context) error {
return ctx.String("Hello")
})
go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
conn, err := net.Dial("tcp", ":8080")
assert.Nil(t, err)
defer conn.Close()
_, err = io.WriteString(conn, "GET / HTTP/1.1\r\nBadHeader\r\nGood: Header\r\n\r\n")
assert.Nil(t, err)
buffer := make([]byte, len("HTTP/1.1 200"))
_, err = conn.Read(buffer)
assert.Nil(t, err)
assert.Equal(t, string(buffer), "HTTP/1.1 200")
}()
s.Run(":8080")
}
func TestBadRequestMethod(t *testing.T) {
s := web.NewServer()
go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
conn, err := net.Dial("tcp", ":8080")
assert.Nil(t, err)
defer conn.Close()
_, err = io.WriteString(conn, "BAD-METHOD / HTTP/1.1\r\n\r\n")
assert.Nil(t, err)
response, err := io.ReadAll(conn)
assert.Nil(t, err)
assert.Equal(t, string(response), "HTTP/1.1 400 Bad Request\r\n\r\n")
}()
s.Run(":8080")
}
func TestBadRequestProtocol(t *testing.T) {
s := web.NewServer()
s.Get("/", func(ctx web.Context) error {
return ctx.String("Hello")
})
go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
conn, err := net.Dial("tcp", ":8080")
assert.Nil(t, err)
defer conn.Close()
_, err = io.WriteString(conn, "GET /\r\n\r\n")
assert.Nil(t, err)
buffer := make([]byte, len("HTTP/1.1 200"))
_, err = conn.Read(buffer)
assert.Nil(t, err)
assert.Equal(t, string(buffer), "HTTP/1.1 200")
}()
s.Run(":8080")
}
func TestEarlyClose(t *testing.T) {
s := web.NewServer()
go func() {
defer syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
conn, err := net.Dial("tcp", ":8080")
assert.Nil(t, err)
_, err = io.WriteString(conn, "GET /\r\n")
assert.Nil(t, err)
err = conn.Close()
assert.Nil(t, err) assert.Nil(t, err)
}() }()