// +build !race
package gig
import (
"crypto/tls"
"io"
"net"
"syscall"
"testing"
"time"
"github.com/matryer/is"
)
type errorListener struct {
errs []error
}
func (l *errorListener) Accept() (c net.Conn, err error) {
if len(l.errs) == 0 {
return nil, io.EOF
}
err = l.errs[0]
l.errs = l.errs[1:]
return
}
func (l *errorListener) Close() error {
return nil
}
func (l *errorListener) Addr() net.Addr {
return &FakeAddr{}
}
func TestServe_NetError(t *testing.T) {
is := is.New(t)
ln := &errorListener{[]error{
&net.OpError{
Op: "accept",
Err: syscall.EMFILE,
}}}
g := New()
g.listener = ln
err := g.serve()
is.Equal(io.EOF, err)
}
func TestServe(t *testing.T) {
is := is.New(t)
g := New()
go func() {
_ = g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
_, err = conn.Write([]byte("/test\r\n"))
is.NoErr(err)
buf := make([]byte, 15)
n, err := conn.Read(buf)
is.NoErr(err)
is.Equal("51 Not Found\r\n\x00", string(buf))
is.Equal(14, n)
g.Close()
}
func TestServe_SlowClient_Read(t *testing.T) {
is := is.New(t)
g := New()
g.ReadTimeout = 1 * time.Millisecond
go func() {
_ = g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
time.Sleep(200 * time.Millisecond) // client sleeps before sending request
_, err = conn.Write([]byte("/test\r\n"))
is.True(err != nil)
g.Close()
}
func TestServe_SlowClient_Write(t *testing.T) {
is := is.New(t)
g := New()
g.WriteTimeout = 1 * time.Millisecond
go func() {
err := g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
if err != ErrServerClosed { // Prevent the test to fail after closing the servers
is.NoErr(err)
}
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
_, err = conn.Write([]byte("/test\r\n"))
is.NoErr(err)
conn.Close() // client closes connection before reading response
g.Close()
}
func TestServe_Overflow(t *testing.T) {
is := is.New(t)
g := New()
go func() {
_ = g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
request := make([]byte, 2000)
_, _ = conn.Write(request)
buf := make([]byte, 23)
n, err := conn.Read(buf)
is.NoErr(err)
is.Equal("59 Request too long!\r\n\x00", string(buf))
is.Equal(22, n)
g.Close()
}
func TestServe_NotGemini(t *testing.T) {
is := is.New(t)
g := New()
go func() {
_ = g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
_, err = conn.Write([]byte("http://google.com\r\n"))
is.NoErr(err)
buf := make([]byte, 40)
n, err := conn.Read(buf)
is.NoErr(err)
is.Equal("59 No proxying to non-Gemini content!\r\n\x00", string(buf))
is.Equal(39, n)
g.Close()
}
func TestServe_NotURL(t *testing.T) {
is := is.New(t)
g := New()
go func() {
_ = g.Run("127.0.0.1:0", "_fixture/certs/cert.pem", "_fixture/certs/key.pem")
}()
time.Sleep(200 * time.Millisecond)
addr := g.listener.Addr().String()
conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
is.NoErr(err)
_, err = conn.Write([]byte("::::::\r\n"))
is.NoErr(err)
buf := make([]byte, 24)
n, err := conn.Read(buf)
is.NoErr(err)
is.Equal("59 Error parsing URL!\r\n\x00", string(buf))
is.Equal(23, n)
g.Close()
}
Source