WIP improve test coverage

There is a test of Response.Read that is failing and I haven't yet
figured out why.
This commit is contained in:
tjpcc 2023-01-11 11:41:07 -07:00
parent e183f9cd23
commit 4969e33e28
3 changed files with 184 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
coverage.out

View File

@ -3,6 +3,7 @@ package gemini_test
import (
"bytes"
"testing"
"net/url"
"tildegit.org/tjp/gus/gemini"
)
@ -84,3 +85,19 @@ func TestParseRequest(t *testing.T) {
})
}
}
func TestUnescapedQuery(t *testing.T) {
table := []string{
"foo bar",
}
for _, test := range table {
t.Run(test, func(t *testing.T) {
u, _ := url.Parse("gemini://domain.com/path?" + url.QueryEscape(test))
result := gemini.Request{ URL: u }.UnescapedQuery()
if result != test {
t.Errorf("expected %q, got %q", test, result)
}
})
}
}

View File

@ -149,3 +149,169 @@ func TestBuildResponses(t *testing.T) {
})
}
}
func TestParseResponses(t *testing.T) {
table := []struct {
input string
status gemini.Status
meta string
body string
err error
}{
{
input: "20 text/gemini\r\n# you got me!\n",
status: gemini.StatusSuccess,
meta: "text/gemini",
body: "# you got me!\n",
},
{
input: "30 gemini://some.where/else\r\n",
status: gemini.StatusTemporaryRedirect,
meta: "gemini://some.where/else",
},
{
input: "10 forgot the line ending",
err: gemini.InvalidResponseLineEnding,
},
{
input: "10 wrong line ending\n",
err: gemini.InvalidResponseLineEnding,
},
{
input: "10no space\r\n",
err: gemini.InvalidResponseHeaderLine,
},
{
input: "no status code\r\n",
err: gemini.InvalidResponseHeaderLine,
},
{
input: "31 gemini://domain.com/my/new/home\r\n",
status: gemini.StatusPermanentRedirect,
meta: "gemini://domain.com/my/new/home",
},
}
for _, test := range table {
t.Run(test.input, func(t *testing.T) {
response, err := gemini.ParseResponse(bytes.NewBufferString(test.input))
if !errors.Is(err, test.err) {
t.Fatalf("expected error %s, got %s", test.err, err)
}
if err != nil {
return
}
if response.Status != test.status {
t.Errorf("expected status %d, got %d", test.status, response.Status)
}
if response.Meta != test.meta {
t.Errorf("expected meta %q, got %q", test.meta, response.Meta)
}
if response.Body == nil {
if test.body != "" {
t.Errorf("expected body %q, got nil", test.body)
}
} else {
body, err := io.ReadAll(response.Body)
if err != nil {
t.Fatalf("error reading response body: %s", err.Error())
}
if test.body != string(body) {
t.Errorf("expected body %q, got %q", test.body, string(body))
}
}
})
}
}
func TestResponseClose(t *testing.T) {
body := &rdCloser{Buffer: bytes.NewBufferString("the body here")}
resp := &gemini.Response{
Status: gemini.StatusSuccess,
Meta: "text/gemini",
Body: body,
}
if err := resp.Close(); err != nil {
t.Fatalf("response close error: %s", err.Error())
}
if !body.closed {
t.Error("response body was not closed by response.Close()")
}
resp = &gemini.Response{
Status: gemini.StatusInput,
Meta: "give me more",
}
if err := resp.Close(); err != nil {
t.Fatalf("response close error: %s", err.Error())
}
}
type rdCloser struct {
*bytes.Buffer
closed bool
}
func (rc *rdCloser) Close() error {
rc.closed = true
return nil
}
func TestResponseWriteTo(t *testing.T) {
// invariant under test: WriteTo() sends the same bytes as Read()
clone := func(resp *gemini.Response) *gemini.Response {
other := &gemini.Response{
Status: resp.Status,
Meta: resp.Meta,
}
if resp.Body != nil {
// the body could be one-time readable, so replace it with a buffer
buf, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("error reading response body: %s", err.Error())
}
resp.Body = bytes.NewBuffer(buf)
buf2 := make([]byte, len(buf))
if copy(buf2, buf) != len(buf) {
t.Fatalf("short copy on a []byte")
}
other.Body = bytes.NewBuffer(buf2)
}
return resp
}
r1 := &gemini.Response{
Status: gemini.StatusSuccess,
Meta: "text/gemini",
Body: bytes.NewBufferString("the body goes here"),
}
r2 := clone(r1)
wtbuf := &bytes.Buffer{}
if _, err := r1.WriteTo(wtbuf); err != nil {
t.Fatalf("response.WriteTo(): %s", err.Error())
}
rdbuf := make([]byte, wtbuf.Len())
if n, err := r2.Read(rdbuf); err != nil {
t.Fatalf("response.Read() -> %d: %s", n, err.Error())
}
if wtbuf.String() != string(rdbuf) {
t.Fatalf("Read produced %q but WriteTo produced %q", string(rdbuf), wtbuf.String())
}
}